import java.util.ArrayList;
import java.util.List;

public class PrimosParaleloComRegiaoCritica extends Thread {
	private int inicio;
	private int fim;

	private static List<Integer> listaDePrimos;

	private PrimosParaleloComRegiaoCritica(int inicio, int fim) {
		this.inicio = inicio;
		this.fim = fim;
	}

	public static List<Integer> buscaPrimos(int intervaloInicio,
			int intervaloFim, int numThreads) throws InterruptedException {
		listaDePrimos = new ArrayList<Integer>();

		List<PrimosParaleloComRegiaoCritica> threads = inicializaThreads(
				intervaloInicio, intervaloFim, numThreads);

		for (Thread thread : threads) {
			thread.start();
		}
		for (Thread thread : threads) {
			thread.join();
		}

		return listaDePrimos;
	}

	public void run() {
//		long antes = System.nanoTime();
		for (int i = this.inicio; i <= this.fim; i++) {
			if (AlgoritmoPrimos.ehPrimo(i)) {
				synchronized (listaDePrimos) {
					listaDePrimos.add(i);
				}
			}
		}
//		long depois = System.nanoTime();
//		long tempoEmNs = depois - antes;
//		System.out.println("Thread do intervalo [" + inicio + "," + fim
//				+ "] acabou em " + tempoEmNs + " nanossegundos ("
//				+ (tempoEmNs / 1000000F) + " milissegundos)");
	}

	private static List<PrimosParaleloComRegiaoCritica> inicializaThreads(
			int inicio, int fim, int numThreads) {
		int blocos = ((fim - inicio) + 1) / numThreads;

		int inicioAux = inicio;
		int fimAux = inicioAux + blocos;

		List<PrimosParaleloComRegiaoCritica> listaThreads = new ArrayList<PrimosParaleloComRegiaoCritica>();
		for (int i = 0; i < numThreads; i++) {
			if ((fimAux) > fim) {
				fimAux = fim;
			}

			PrimosParaleloComRegiaoCritica pi = new PrimosParaleloComRegiaoCritica(
					inicioAux, fimAux);
			listaThreads.add(pi);

			inicioAux = (fimAux + 1);
			fimAux = inicioAux + blocos;
		}

		return listaThreads;
	}
}
